package com.demo.springsecuritystudy.configuration;

import com.demo.springsecuritystudy.handle.SecurityAccessDeniedHandler;
import com.demo.springsecuritystudy.service.UserDetailServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.annotation.Resource;
import javax.sql.DataSource;

//@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

//    @Resource
    private SecurityAccessDeniedHandler securityAccessDeniedHandler;

//    @Resource
    private UserDetailServiceImpl userDetailServiceImpl;

//    @Resource
    private DataSource dataSource;

//    @Resource
    private PersistentTokenRepository persistentTokenRepository;

    /**
     * 将Spring Security默认的登录页面路由到自定义的登录页面.
     * 由于重写了configure方法,所以需要<code>httpSecurity.authorizeRequests()
     * .anyRequest().authenticated();</code>来进行所有请求的拦截验证。
     * 同时需要对login.html进行放行不需要验证。同时对/login请求进行
     * 拦截,登录成功后会跳转到main.html,登录失败跳转到error.html。
     * 同时需要关闭csrf防护.
     * @param httpSecurity
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.formLogin()
                .loginProcessingUrl("/login")
                .loginPage("/showLogin")
                .successForwardUrl("/toMain")
                // 登陆成功重定向到https://www.baidu.com
//                .successHandler(new SecurityAuthenticationSuccessHandler("/main.html"))
                .failureForwardUrl("/toError");
                // 登录失败重定向到error.html
//                .failureHandler(new SecurityAuthenticationFailureHandler("/error.html"));
        httpSecurity.authorizeRequests()
                // 可以写多条对不同的url进行权限认证
                .antMatchers("/error.html")
                // 允许访问的权限
                .permitAll()
                .antMatchers("/showLogin")
                .permitAll()
//                .anyRequest()
                // 注意是beanName不是类名
//                .access("@securityServiceImpl.hasPermission(request, authentication)");
//                .antMatchers("/main.html")
//                .hasIpAddress("localhost")
                // 所有请求都会被认证
                .anyRequest()
                .authenticated();

//        httpSecurity.csrf().disable();
        httpSecurity.exceptionHandling()
                    .accessDeniedHandler(securityAccessDeniedHandler);

        httpSecurity.rememberMe()
                    // 失效时间,单位:秒
                    .tokenValiditySeconds(60)
                    // 设置remember-me的别名
                    .rememberMeParameter("remember-me-alias")
                    .userDetailsService(userDetailServiceImpl)
                    // 持久层对象
                    .tokenRepository(persistentTokenRepository);
        httpSecurity.logout()
                    .logoutSuccessUrl("/logout");
    }

    @Bean
    public PasswordEncoder getPasswordEncode() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository getPersistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        // 自动建表,第一次启动需要,第二次启动需要启动
//        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }
}
